import java.util.*;
import common.*;

public class Initializer
{
	static String protocol;
	static String [] IPs;
	static int [] numNodes;
	static int groupNumber;
	static ArrayList<Process> localProcesses;
	//public static final int PORT = 9000;
	//public static final int sleepTime = 2000;
	static Scanner scan;
	
	// guess Initializer itself also needs to be a thread, so that it can ping its child nodes periodically --charmgil
	// public void run(){}
	
	// this function will simplify sending a ping msg.
	// this can be moved to wherever the one who periodically pings every node is located
	public void ping( int rcv_id )
	{
		//Message msg = new Message( Def.PING, rcv_id, (router_id), System.currentTimeMillis(), "", null );
		//send( msg );
			// - we need to assign router IDs. We can reserve negative numbers for this.
			//     =>  when an ID > 0 : it's a node,
			//                 ID = 0 : for broadcasting
			//                 ID < 0 : it's a router
	}
	
	public static void main(String [] args)
	{
		Monitor console;
		
		scan = new Scanner(System.in);
		if(args.length != 6)
		{
			System.out.println("Usage Error: java Initializer [protocol] <group1IP> <number of nodes> <group2IP> <number of nodes> myGroup");
			System.exit(0);
		}
		protocol = args[0];
		IPs = new String[2];
		IPs[0] = args[1];
		numNodes = new int[2];
		numNodes[0] = Integer.parseInt(args[2]);
		IPs[1] = args[3];
		//Initialize numNodes[1] to the sum of the nodes for easier use later.
		numNodes[1] = Integer.parseInt(args[4])+numNodes[0];
		groupNumber = Integer.parseInt(args[5])-1;
		
		MessagePasser.partnerIPs = new ArrayList<String>();
		MessagePasser.partnerPorts = new ArrayList<Integer>();
		//Build the network topology
		for(int i = 0; i < numNodes[0]; i++)
		{
			MessagePasser.partnerIPs.add(i, IPs[0]);
			MessagePasser.partnerPorts.add(i, (Conf.STARTING_PORT_NO+i));
		}
		for(int i = numNodes[0]; i < numNodes[1]; i++)
		{
			MessagePasser.partnerIPs.add(i, IPs[1]);
			MessagePasser.partnerPorts.add(i, (Conf.STARTING_PORT_NO+i));
		}
		
		//Build the local processes information
		localProcesses = new ArrayList<Process>();
		if(groupNumber == 1)
		{
			Utils.print_log("Initializing this process to " + numNodes[0] + " through " + numNodes[1]); 
			for(int i = numNodes[0]; i < numNodes[1]; i++)
			{
				localProcesses.add((i - numNodes[0]), new Process(i, Conf.THREAD_SLEEPTIME_MS));	// sleepTime));
				
				// charmgil added
				if( i == numNodes[0] ) localProcesses.get(i - numNodes[0]).get_shell().turnon();
			}
		}
		else
		{
			Utils.print_log("Initializing this process to 0 through " + (numNodes[0]-1));
			for(int i = 0; i < numNodes[0]; i++)
			{
				localProcesses.add(i, new Process(i, Conf.THREAD_SLEEPTIME_MS));	// sleepTime));
				
				// charmgil added
				if( i == 0 ) localProcesses.get(i).get_shell().turnon();
			}
		}
		System.out.println("Finished building all local nodes, press enter when other initializers are here.");
		scan.nextLine();
		for(int i = 0; i < localProcesses.size(); i++)
		{
			for(int j = 0; j < MessagePasser.partnerPorts.size(); j++)
			{
				if(i!=j)
				{
					localProcesses.get(i).addPartner(j);
				}
			}
		}
		System.out.println("Finished building node graph.");
		scan.nextLine();
		for(Process p : localProcesses)
		{
			p.start();
		}
		Monitor.autoexec();
		
		// management console (for the experiment)
		if( Conf.MGMT_CONSOLE ){
			console = new Monitor( localProcesses );
			console.start();
		}
	}//end-of-main()
}//end-of-class